/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package Control;

import Model.*;
import View.SourceCodeWindow;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import jdk.nashorn.internal.runtime.arrays.ArrayData;

/**
 *
 * @author Alan Carlos
 * @author João Vilas Boas
 */
/*
Classe responsavel por controlar a chamada aos automatos, que processarão
o codigo fonte. Faz o intermedio com a interface gráfica, imprimindo a tabela de 
simbolos e a de erros léxicos.


*/

public class Triagem {

    private int[][] arrayIndex;
    private Collection<IndexTexto> indexTextoCollection;
    private String texto;
    private SourceCodeWindow viewMain;
    public final static char EOF = '\u001a';

    public Triagem(SourceCodeWindow viewMain) {
        this.viewMain = viewMain;
        viewMain.getjButtonCompiler().addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonCompilerActionPerformed(evt);
            }
        });
        // indexTextoCollection = new ArrayList<IndexTexto>();
    }

    private void jButtonCompilerActionPerformed(java.awt.event.ActionEvent evt) {
        //captura todo o texto e o salva em uma string    
        this.texto = viewMain.getjTextAreaSourceCode().getText();  
        //Adiciona caractere que marca o fim do arquivo EOF 
        texto = texto + '\u001a'; 

        TableLexema.getInstance().setIndex(texto); // indexar cada caractere de todo o codigo fonte
      
        Automato automato = new Automato(viewMain);
        char currentChar;
        char fowardChar;
      
        for (int i = 0; i < texto.length(); i++) {
           
            currentChar = texto.charAt(i);
          
            if (currentChar == '\u001a') {
                break; //Chegou ao final do texto, todos os tokens ja processados, sair do laço
            }

            if (currentChar == '\n') {
                //se houver uma quebra de linha, incrementar o valor de row
                TableLexema.getInstance().incrementRow();

            } else {
                //caso contrario, incrementar coluna a cada caractere lido
                TableLexema.getInstance().incrementColumn();
            }

            //bloco de condicionais que chamará cada automato de acordo com os carateres lidos
            if (automato.getLetter().contains(currentChar)) {
                i = automato.checkIdentifiers(texto, i);
            } else if (automato.getDigit().contains(currentChar)) {
                i = automato.checkNumbers(texto, i);
            } else if (automato.getDelimeters().contains(currentChar)) {
                i = automato.checkDelimiter(texto, i);
            } else if (currentChar == '-') { //irá decidir se é operador ou dígito
                char previousChar = ' ';
                if (i > 0) {
                    previousChar = texto.charAt(i - 1);
                }
                fowardChar = texto.charAt(i + 1); //próximo caractere.
                if (automato.getIdentifier().contains(previousChar)
                        || automato.getDigit().contains(previousChar)
                        || automato.getOperator().contains(previousChar)) {
                    i = automato.checkOperator(texto, i);
                } else if (automato.getDigit().contains(fowardChar)) {
                    i = automato.checkNumbers(texto, i);        //chama o automato que reconhece numeros
                } else {
                    i = automato.checkOperator(texto, i);
                }
            } else if (currentChar == '/') { //decidirá se é operador ou comentário
                fowardChar = texto.charAt(i + 1);
                if (fowardChar == '/' || fowardChar == '*') {
                    i = automato.checkComments(texto, i);
                } else {
                    System.out.println("Lexema Operador -->" + currentChar);
                    TableLexema.getInstance().addToList(String.valueOf(currentChar), i, 6);
                }
            } else if (automato.getOperator().contains(currentChar)) {
                i = automato.checkOperator(texto, i);
            } else if (currentChar == (char) 34) { //charactere "
                i = automato.checkString(texto, i);// checagem de string
                //int[] rowColumn = getRowColumn(i);
            } else if (currentChar == (char) 39) { //character '
                i = automato.checkChar(texto, i);
            } else if (currentChar != ' ' && !automato.elementText(currentChar)) {
                System.out.println("Erro símbolo inválido -->" + currentChar);
                TableLexema.getInstance().addErrorToList(String.valueOf(currentChar), i, "Erro símbolo inválido");
            
            }
            /*
            UPDATE: Em algumas partes do texo os caracteres ASCII que não fazem parte do
            nosso alfabeto devem aparecer no texto, e esse teste acusa erro. 
            O problema é que esse intervalo da ASCII são caracteres que não são
            imprimiveis, portanto não são mostrados na interface.
            
            
            Identificação de caractere que não pertence ao alfabeto
            else if(automato.getNotAlphabet().contains(currentChar)){
                System.out.println("Erro simbolo não pertence ao alfabeto-->" + currentChar);
                TableLexema.getInstance().addErrorToList(String.valueOf(currentChar), i, "Erro simbolo não pertence ao alfabeto");
              
            }*/

        }

        //UTILIZAR QUANDO QUISER TESTAR O ARRAY DE TOKENS
        for (int i = 0; i < TableLexema.getInstance().getArray().size(); i++) {
            System.out.println("Lexema: " + TableLexema.getInstance().getArray().get(i).getLexema()
                    + "  Linha: " + TableLexema.getInstance().getArray().get(i).getLinha()
                    + "  Coluna: " + TableLexema.getInstance().getArray().get(i).getColuna()
                    + "  Tipo: " + TableLexema.getInstance().getArray().get(i).getTipo());
        }
        //UTILIZAR QUANDO QUISER TESTAR O ARRAY DE ERROS LEXICOS
        System.out.println("\n\n\n\n");
        for (int i = 0; i < TableLexema.getInstance().getErrorTable().size(); i++) {
            System.out.println(" Lexema: " + TableLexema.getInstance().getErrorTable().get(i).getLexema()
                    + "  Linha: " + TableLexema.getInstance().getErrorTable().get(i).getLinha()
                    + "  Coluna: " + TableLexema.getInstance().getErrorTable().get(i).getColuna()
                    + "  Tipo Erro: " + TableLexema.getInstance().getErrorTable().get(i).getTipoErro());
        }
        setTableTokensWindow();
        //setTableErrorLexicoWindow();
        Parser parser = new Parser();
        setTableErrorLexicoWindow();
        
    }

    private void setTableTokensWindow() { // metodo usado para inserir os valores na tabela.
        String conteudo[][] = new String[TableLexema.getInstance().getArray().size()][4];
        JTable jTableTokens = viewMain.getjTableTokens();

        for (int i = 0; i < TableLexema.getInstance().getArray().size(); i++) { //converte o ArrayList em matriz[][].
            conteudo[i][0] = TableLexema.getInstance().getArray().get(i).getLexema();
            conteudo[i][1] = String.valueOf(TableLexema.getInstance().getArray().get(i).getLinha());
            conteudo[i][2] = String.valueOf(TableLexema.getInstance().getArray().get(i).getColuna());
           
            switch (TableLexema.getInstance().getArray().get(i).getTipo()) {
                case Token.IDENTIFICADOR:
                    conteudo[i][3] = "Identificador";
                    break;
                case Token.PALAVRA_RESERVADA:
                    conteudo[i][3] = "Palavra Reservada";
                    break;
                case Token.SIMBOLO:
                    conteudo[i][3] = "Símbolo";
                    break;
                case Token.STRING:
                    conteudo[i][3] = "String";
                    break;
                case Token.CARACTERE:
                    conteudo[i][3] = "Caractere";
                    break;
                case Token.OPERADOR:
                    conteudo[i][3] = "Operador";
                    break;
                case Token.DELIMITADOR:
                    conteudo[i][3] = "Delimitador";
                    break;
                case Token.NUMERO:
                    conteudo[i][3] = "Número";
                    break;
                default :
                    conteudo[i][3] = "Desconhecido";
                    break;
            }

        }
        DefaultTableModel modelTable = new DefaultTableModel(conteudo, new String[]{"Lexema", "Linha", "Coluna", "Tipo"});
        jTableTokens.setModel(modelTable);
        jTableTokens.setEnabled(false);
       
        
    }

    private void setTableErrorLexicoWindow() {// metodo usado para inserir os valores na tabela de erro.
        int row = TableLexema.getInstance().getErrosSintaticos().size() + TableLexema.getInstance().getErrorTable().size();
        String conteudo[][] = new String[row][4];
        JTable jTableErrolexico = viewMain.getjTableErroLexico();
        int i=0;
        int aux=0;
        for (i=aux; i < TableLexema.getInstance().getErrorTable().size(); i++) { //converte o ArrayList em matriz[][].
            conteudo[i][0] = TableLexema.getInstance().getErrorTable().get(i).getLexema();
            conteudo[i][1] = String.valueOf(TableLexema.getInstance().getErrorTable().get(i).getLinha());
            conteudo[i][2] = String.valueOf(TableLexema.getInstance().getErrorTable().get(i).getColuna());
            conteudo[i][3] = String.valueOf(TableLexema.getInstance().getErrorTable().get(i).getTipoErro());

        }
        aux=i;
        for (i=aux; i < TableLexema.getInstance().getErrosSintaticos().size(); i++) { //converte o ArrayList em matriz[][].
            conteudo[i][0] = TableLexema.getInstance().getErrosSintaticos().get(i).getSintatico();
            conteudo[i][1] = String.valueOf(TableLexema.getInstance().getErrosSintaticos().get(i).getLinha());
            conteudo[i][2] = String.valueOf(TableLexema.getInstance().getErrosSintaticos().get(i).getColuna());
            conteudo[i][3] = String.valueOf(TableLexema.getInstance().getErrosSintaticos().get(i).getTipoErro());

        }
        aux=i;
        for (i=aux; i < TableLexema.getInstance().getErrosSemanticos().size(); i++) { //converte o ArrayList em matriz[][].
            conteudo[i][0] = TableLexema.getInstance().getErrosSemanticos().get(i).getSemantico();
            conteudo[i][1] = String.valueOf(TableLexema.getInstance().getErrosSemanticos().get(i).getLinha());
            conteudo[i][2] = String.valueOf(TableLexema.getInstance().getErrosSemanticos().get(i).getColuna());
            conteudo[i][3] = String.valueOf(TableLexema.getInstance().getErrosSemanticos().get(i).getTipoErro());

        }
        
        DefaultTableModel modelTable = new DefaultTableModel(conteudo, new String[]{"Lexema", "Linha", "Coluna", "Tipo"});
        jTableErrolexico.setModel(modelTable);
        jTableErrolexico.setEnabled(false);
        jTableErrolexico.getColumnModel().getColumn(3).setPreferredWidth(250);
    }
    
    private void setTableErrorSintaticoWindow(int index) {// metodo usado para inserir os valores na tabela de erro.
        String conteudo[][] = new String[TableLexema.getInstance().getErrosSintaticos().size()][4];
        //JTable jTableErrolexico = viewMain.getjTableErroLexico();
        int i = index;
        for (i = index; i < TableLexema.getInstance().getErrosSintaticos().size(); i++) { //converte o ArrayList em matriz[][].
            conteudo[i][0] = TableLexema.getInstance().getErrosSintaticos().get(i).getSintatico();
            conteudo[i][1] = String.valueOf(TableLexema.getInstance().getErrosSintaticos().get(i).getLinha());
            conteudo[i][2] = String.valueOf(TableLexema.getInstance().getErrosSintaticos().get(i).getColuna());
            conteudo[i][3] = String.valueOf(TableLexema.getInstance().getErrosSintaticos().get(i).getTipoErro());

        }
       /* DefaultTableModel modelTable = new DefaultTableModel(conteudo, new String[]{"Lexema", "Linha", "Coluna", "Tipo"});
        jTableErrolexico.setModel(modelTable);
        jTableErrolexico.setEnabled(false);
        jTableErrolexico.getColumnModel().getColumn(3).setPreferredWidth(250);*/
    }
}
